package cn.zd.thumbbackend.service.impl;

import cn.zd.thumbbackend.constant.ThumbConstant;
import cn.zd.thumbbackend.exception.ErrorCode;
import cn.zd.thumbbackend.exception.ThrowUtils;
import cn.zd.thumbbackend.manager.cache.CacheManager;
import cn.zd.thumbbackend.model.dto.thumb.DoThumbRequest;
import cn.zd.thumbbackend.model.entity.Blog;
import cn.zd.thumbbackend.model.entity.User;
import cn.zd.thumbbackend.service.BlogService;
import cn.zd.thumbbackend.service.UserService;
import cn.zd.thumbbackend.util.RedisKeyUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.zd.thumbbackend.model.entity.Thumb;
import cn.zd.thumbbackend.service.ThumbService;
import cn.zd.thumbbackend.mapper.ThumbMapper;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;


/**
 * @author zheng
 * @description 针对表【thumb】的数据库操作Service实现
 * @createDate 2025-05-20 14:44:44
 */
@Service("thumbService")
@Slf4j
@RequiredArgsConstructor
public class ThumbServiceImpl extends ServiceImpl<ThumbMapper, Thumb>
        implements ThumbService {
    
    private final UserService userService;
    
    private final BlogService blogService;
    
    private final TransactionTemplate transactionTemplate;
    
    private final RedisTemplate<String, Object> redisTemplate;
    
    // 引入缓存管理
    private final CacheManager cacheManager;
    
    
    /**
     * 点赞
     *
     * @param doThumbRequest doThumbRequest
     * @param request        request
     * @return {@link Boolean }
     */
    @Override
    public Boolean doThumb(DoThumbRequest doThumbRequest, HttpServletRequest request) {
        ThrowUtils.throwIf((doThumbRequest == null || doThumbRequest.getBlogId() == null), ErrorCode.PARAMS_ERROR);
        User loginUser = userService.getLoginUser(request);
        ThrowUtils.throwIf(loginUser == null, ErrorCode.NOT_LOGIN_ERROR);
        // 加锁
        synchronized (loginUser.getId().toString().intern()) {
            // 编程式事务
            return transactionTemplate.execute(status -> {
                Long blogId = doThumbRequest.getBlogId();
                Boolean exists = this.hasThumb(blogId, loginUser.getId());
                ThrowUtils.throwIf(exists, ErrorCode.HAS_THUMB);
                boolean update = blogService.lambdaUpdate()
                        .eq(Blog::getId, blogId)
                        .setSql(" thumbcount = thumbcount + 1 ")
                        .update();
                
                Thumb thumb = new Thumb();
                thumb.setUserid(loginUser.getId());
                thumb.setBlogid(blogId);
                
                boolean success = update && this.save(thumb);
                // 点赞记录存入 Redis
                if (success) {
                    String hashKey = ThumbConstant.USER_THUMB_KEY_PREFIX + loginUser.getId();
                    String fieldKey = blogId.toString();
                    Long realThumbId = thumb.getId();
                    redisTemplate.opsForHash().put(hashKey, fieldKey, realThumbId);
                    cacheManager.putIfPresent(hashKey, fieldKey, realThumbId);
                }
                // 更新成功才执行
                return success;
            });
        }
    }
    
    /**
     * 取消点赞
     *
     * @param doThumbRequest doThumbRequest
     * @param request        request
     * @return {@link Boolean }
     */
    @Override
    public Boolean undoThumb(DoThumbRequest doThumbRequest, HttpServletRequest request) {
        ThrowUtils.throwIf((doThumbRequest == null || doThumbRequest.getBlogId() == null), ErrorCode.PARAMS_ERROR);
        User loginUser = userService.getLoginUser(request);
        ThrowUtils.throwIf(loginUser == null, ErrorCode.NOT_LOGIN_ERROR);
        // 加锁
        synchronized (loginUser.getId().toString().intern()) {
            return transactionTemplate.execute(status -> {
                Long blogId = doThumbRequest.getBlogId();
                Object thumbObj = cacheManager.get(ThumbConstant.USER_THUMB_KEY_PREFIX + loginUser.getId(), blogId.toString());
                ThrowUtils.throwIf((thumbObj == null || thumbObj.equals(ThumbConstant.UN_THUMB_CONSTANT)), ErrorCode.NO_HAS_THUMB);
                boolean update = blogService.lambdaUpdate()
                        .eq(Blog::getId, blogId)
                        .setSql(" thumbcount = thumbcount - 1 ")
                        .update();
                Long thumbId = Long.valueOf(thumbObj.toString());
                boolean success = update && this.removeById(thumbId);
                // 点赞记录从 Redis 删除
                if (success) {
                    String hashKey = ThumbConstant.USER_THUMB_KEY_PREFIX + loginUser.getId();
                    String fieldKey = blogId.toString();
                    redisTemplate.opsForHash().delete(hashKey, fieldKey);
                    cacheManager.putIfPresent(hashKey, fieldKey, ThumbConstant.UN_THUMB_CONSTANT);
                }
                return success;
            });
        }
    }
    
    /**
     * 是否点赞
     *
     * @param blogId blogId
     * @param userId userId
     * @return {@link Boolean }
     */
    @Override
    public Boolean hasThumb(Long blogId, Long userId) {
        Object thumbObj = cacheManager.get(ThumbConstant.USER_THUMB_KEY_PREFIX + userId, blogId.toString());
        if (thumbObj == null) return false;
        Long thumbId = (Long) thumbObj;
        return !thumbId.equals(ThumbConstant.UN_THUMB_CONSTANT);
    }
    
    
}




